#include "game.h"

#include <QDebug>
#include <QMessageBox>

Game::Game() : server(nullptr), serverThread(nullptr)
{
    client = new GameClient;

    fw = new Widget;
    gw = new GameWindow(client);

    fw->setServerAddress("127.0.0.1");
    fw->setServerPort("23333");
    fw->enableServerMode(true);

    initConnections();
    showWidgets(true);
}

void Game::showWidgets(bool initial)
{
    if (initial) {
        fw->show();
        gw->hide();
    } else {
        fw->hide();
        gw->show();
    }
}

void Game::initConnections()
{
    connect(fw, &Widget::launchServer, this, &Game::startServer);
    connect(fw, &Widget::launchClient, this, &Game::startClient);

    connect(client, &GameClient::clientStopping, this, &Game::onClientStopping);
    connect(client, &GameClient::startGame, this, &Game::startGame);
}

// client requests to stop
void Game::onClientStopping(const QString& why)
{
    stopClient();
    // if server is running, it should also stop
    if (server)
        stopServer();

    QMessageBox::warning(nullptr, "Ooops", why);
    fw->close();
    gw->close();
}

void Game::startClient(const QHostAddress& address, quint16 port)
{
    bool connected = client->connectToServer(address, port);
    if (!connected) {
        QString msg = "failed to connect to" + address.toString() + ":" + QString::number(port);
        onClientStopping(msg);
    }
}

void Game::startServer(quint16 port)
{
    // when GameServer is derived from QThread
    // server = new GameServer();
    // server->setPort(port);
    // server->moveToThread(server);
    // server->start();

    server = new GameServer;
    serverThread = new QThread;
    serverThread->start();

    if (!server->start(port, serverThread))
        stopServer();
}

void Game::stopClient()
{
    client->stop();
}

void Game::stopServer()
{
    qDebug("[G] terminating server thread...");
    serverThread->terminate();

    delete server;
    server = nullptr;

    serverThread->wait();
    delete serverThread;
    qDebug("[G] server stopped.");
}

void Game::startGame()
{
    showWidgets(false);
}

Game::~Game()
{
    // fw, gw, client should always be non-null
    if (fw) delete fw;
    if (gw) delete gw;
    if (client) delete client;
    if (server) stopServer();
}
